import tkinter as tk
from tkinter import filedialog, ttk, scrolledtext
import re
import os
from collections import defaultdict


class BibAnalyzerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("BIB文件分析工具")
        self.root.geometry("900x700")

        # 设置界面样式
        self.style = ttk.Style()
        self.style.configure("TButton", font=("Arial", 10))
        self.style.configure("TLabel", font=("Arial", 11))
        self.style.configure("Heading.TLabel", font=("Arial", 12, "bold"))

        # 创建主框架
        self.main_frame = ttk.Frame(root, padding=10)
        self.main_frame.pack(fill=tk.BOTH, expand=True)

        # 文件选择区域
        self.file_frame = ttk.Frame(self.main_frame)
        self.file_frame.pack(fill=tk.X, pady=10)

        self.file_label = ttk.Label(self.file_frame, text="选择BIB文件:", style="TLabel")
        self.file_label.pack(side=tk.LEFT, padx=5)

        self.file_path = tk.StringVar()
        self.file_entry = ttk.Entry(self.file_frame, textvariable=self.file_path, width=50)
        self.file_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)

        self.browse_button = ttk.Button(self.file_frame, text="浏览", command=self.browse_file)
        self.browse_button.pack(side=tk.LEFT, padx=5)

        self.analyze_button = ttk.Button(self.file_frame, text="分析", command=self.analyze_bib)
        self.analyze_button.pack(side=tk.LEFT, padx=5)

        # 创建一个笔记本控件（选项卡）
        self.notebook = ttk.Notebook(self.main_frame)
        self.notebook.pack(fill=tk.BOTH, expand=True, pady=10)

        # 创建选项卡
        self.summary_tab = ttk.Frame(self.notebook)
        self.details_tab = ttk.Frame(self.notebook)

        self.notebook.add(self.summary_tab, text="摘要")
        self.notebook.add(self.details_tab, text="详细信息")

        # 摘要选项卡内容
        self.summary_frame = ttk.Frame(self.summary_tab, padding=10)
        self.summary_frame.pack(fill=tk.BOTH, expand=True)

        self.summary_label = ttk.Label(self.summary_frame, text="文件摘要", style="Heading.TLabel")
        self.summary_label.pack(anchor=tk.W, pady=5)

        self.summary_text = scrolledtext.ScrolledText(self.summary_frame, wrap=tk.WORD, width=80, height=20)
        self.summary_text.pack(fill=tk.BOTH, expand=True, pady=5)
        self.summary_text.config(state=tk.DISABLED)

        # 详细信息选项卡内容
        self.details_frame = ttk.Frame(self.details_tab, padding=10)
        self.details_frame.pack(fill=tk.BOTH, expand=True)

        self.details_label = ttk.Label(self.details_frame, text="条目类型详细信息", style="Heading.TLabel")
        self.details_label.pack(anchor=tk.W, pady=5)

        # 创建一个显示条目类型的列表框
        self.type_frame = ttk.Frame(self.details_frame)
        self.type_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))

        self.type_label = ttk.Label(self.type_frame, text="条目类型")
        self.type_label.pack(anchor=tk.W, pady=5)

        self.type_listbox = tk.Listbox(self.type_frame, width=20, height=25)
        self.type_listbox.pack(fill=tk.BOTH, expand=True)
        self.type_listbox.bind('<<ListboxSelect>>', self.show_type_fields)

        # 创建一个显示字段的文本框
        self.fields_frame = ttk.Frame(self.details_frame)
        self.fields_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        self.fields_label = ttk.Label(self.fields_frame, text="字段列表")
        self.fields_label.pack(anchor=tk.W, pady=5)

        self.fields_text = scrolledtext.ScrolledText(self.fields_frame, wrap=tk.WORD, width=60, height=25)
        self.fields_text.pack(fill=tk.BOTH, expand=True)
        self.fields_text.config(state=tk.DISABLED)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("准备就绪")
        self.status_bar = ttk.Label(root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        # 存储分析结果
        self.entry_types = {}
        self.entries_count = 0

    def browse_file(self):
        file_path = filedialog.askopenfilename(
            filetypes=[("BIB Files", "*.bib"), ("All Files", "*.*")]
        )
        if file_path:
            self.file_path.set(file_path)
            self.status_var.set(f"已选择文件: {os.path.basename(file_path)}")

    def analyze_bib(self):
        file_path = self.file_path.get()
        if not file_path or not os.path.exists(file_path):
            self.status_var.set("错误: 请选择有效的BIB文件")
            return

        try:
            self.status_var.set("正在分析BIB文件...")
            self.root.update_idletasks()

            # 清空之前的结果
            self.entry_types = {}
            self.entries_count = 0

            # 读取并解析BIB文件
            with open(file_path, 'r', encoding='utf-8') as file:
                content = file.read()

            # 使用正则表达式查找所有条目
            entries = re.findall(r'@(\w+)\s*\{([^@]*)(?=@|\Z)', content, re.DOTALL)
            if not entries and content.strip():
                # 尝试匹配最后一个条目（如果只有一个条目或文件末尾没有新的@符号）
                entries = re.findall(r'@(\w+)\s*\{(.*)', content, re.DOTALL)

            # 处理每个条目
            for entry_type, entry_content in entries:
                entry_type = entry_type.lower()

                # 提取关键字和值
                fields = {}
                # 分析字段 (忽略第一行，通常是引用键)
                lines = entry_content.strip().split('\n', 1)
                if len(lines) > 1:
                    field_content = lines[1]
                    # 匹配字段名和值
                    field_matches = re.findall(r'(\w+)\s*=\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}', field_content)
                    for field_name, field_value in field_matches:
                        fields[field_name.lower()] = field_value.strip()

                # 存储条目类型和字段
                if entry_type not in self.entry_types:
                    self.entry_types[entry_type] = defaultdict(int)

                # 计数每个字段在此类型中的出现次数
                for field in fields:
                    self.entry_types[entry_type][field] += 1

                self.entries_count += 1

            # 更新UI
            self.update_summary()
            self.update_types_list()

            self.status_var.set(f"分析完成，共发现 {self.entries_count} 个条目，{len(self.entry_types)} 种类型")

        except Exception as e:
            self.status_var.set(f"错误: {str(e)}")

    def update_summary(self):
        # 更新摘要信息
        self.summary_text.config(state=tk.NORMAL)
        self.summary_text.delete(1.0, tk.END)

        self.summary_text.insert(tk.END, f"文件: {os.path.basename(self.file_path.get())}\n")
        self.summary_text.insert(tk.END, f"条目总数: {self.entries_count}\n")
        self.summary_text.insert(tk.END, f"条目类型数: {len(self.entry_types)}\n\n")

        self.summary_text.insert(tk.END, "条目类型摘要:\n")
        for entry_type, fields in sorted(self.entry_types.items()):
            type_count = sum(1 for _ in fields)
            self.summary_text.insert(tk.END, f"- {entry_type}: {type_count} 个字段\n")

        self.summary_text.config(state=tk.DISABLED)

    def update_types_list(self):
        # 更新条目类型列表
        self.type_listbox.delete(0, tk.END)
        for entry_type in sorted(self.entry_types.keys()):
            self.type_listbox.insert(tk.END, entry_type)

    def show_type_fields(self, event):
        # 显示选定类型的字段
        selection = self.type_listbox.curselection()
        if not selection:
            return

        entry_type = self.type_listbox.get(selection[0])
        fields = self.entry_types.get(entry_type, {})

        self.fields_text.config(state=tk.NORMAL)
        self.fields_text.delete(1.0, tk.END)

        self.fields_text.insert(tk.END, f"类型 '{entry_type}' 的字段:\n\n")

        for field, count in sorted(fields.items(), key=lambda x: (-x[1], x[0])):
            percentage = (count / self.entries_count) * 100
            # self.fields_text.insert(tk.END, f"- {field}: 出现 {count} 次 ({percentage:.1f}%)\n")
            self.fields_text.insert(tk.END, f"- {field}\n")

        self.fields_text.config(state=tk.DISABLED)


def main():
    root = tk.Tk()
    app = BibAnalyzerApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()